#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <string>
#include <Box2D/Box2D.h>
#include <iostream>

#include "datafile.hpp"
#include "texturelist.hpp"
#include "spriteanimate.hpp"
#include "Applejack/world.hpp"
#include "Applejack/body.hpp"
#include "exception.hpp"
#include "container.hpp"
#include "eventmanager.hpp"
#include "renderressources.hpp"
#include <ui.hpp>

// g++ *.cpp -lBox2D -lsfml-graphics -lsfml-system -lsfml-window -lyaml -ldl

using namespace Shiny;
using namespace Applejack;

void Exception::Display(sf::RenderWindow& target)
{
  std::string  _error = _sender + ": " + _originalMessage;
  sf::Text     text(_error);
  unsigned int sizeX;
  sf::Vector2f position;
  sf::Event    event;

  sizeX      = target.GetWidth() / (_error.length() + 2);
  position.x = sizeX;
  position.y = target.GetHeight() / 2 - (sizeX / 2);
  text.SetPosition(position);
  text.SetColor(sf::Color(255, 255, 255));
  target.Draw(text);
  target.Display();
  do
  {
    if (!(target.WaitEvent(event)))
      break ;
  } while ((event.Type != sf::Event::KeyPressed) && (event.Type != sf::Event::MouseButtonPressed));
}

int	main(int argc, char** argv)
{
  sf::RenderWindow	window(sf::VideoMode(800, 600, 32), "Trololo");
  try
  {
    std::string levelPath;

    if (argc == 1)
      levelPath = "./";
    else
      levelPath = std::string(argv[1]) + "/";
    
    std::cout << "Executing Level " << levelPath << std::endl;

    EventManager          eventManager;
    World*                world = (World*)World::Factory::New(levelPath, DataTree::Factory::Yaml(levelPath + "level.yml"));
    bool		  stop  = false;

    world->CreateCanvas(800, 600);

    Body* cameraFocus = world->GetBody("camera_focus");

    if (cameraFocus)
      world->View().SyncWithBody(cameraFocus, 50);

    do
    {
      RenderRessources res;

      //world->Step(1.f / 60.f, 6, 2);
      res = world->Update();

      // /*
      // Using Canvas
      {
        res.Render(world->Canvas());
        world->Canvas().Display();
        window.Draw(sf::Sprite(world->Canvas().GetTexture()));
      }
      // */

      /*
      // Not using canvas
      {
        res.Render(window);
      }
      */

      window.Display();
    } while (!stop && eventManager.Run(window));
  }
  catch (Shiny::Exception exception)
  {
    exception.Display(window);
  }
  return (0);
}
